from myelin.Ns import MYELINS, XML_NS
from myelin.server.core.ft import ModelDriver

from nodetypes.core.DocumentOrdering import OrderByKeys
from nodetypes.ntypes.Document.view.MML import Document, Transform
from nodetypes.Ns import GRAPHS_NS


class Document(Document):
    
    newContentDriver = staticmethod(ModelDriver.FromRepo)
    newAgentDriver = staticmethod(ModelDriver.FromRepo)    
    
    containsKey = u'dcRelated' # must be overriden
    containsAction = u'view'
    groupingKey = u'contains'
    
    def createContent(self, context, node, locale):
        curNode = node.xml_append(
            node.xml_create_element(
                u'a:grouping', MYELINS,
                attributes={
                    u'role' : u'body'
                }
            )
        )
        
        rdf_join = context.model.rdf_join
        curNode.xml_append(
            curNode.xml_create_element(
                u'a:literal', MYELINS,
                attributes = {
                    u'format' : u'application/makara+text',
                    (u'xml:lang', XML_NS) : rdf_join('dcLanguage',u'|'),
                },
                content = rdf_join('mAbstract',u'\n\n')
            )
        )
        
        return self.createContentContainer(context, node, locale)
    
    def getModelByMode(self, context, model):
        driver = context.request.graphs.get(
            context.mode
        )
        #print "pd: %s, %s" % (self.mode, str(driver))
        if driver:
            driver = self.newContentDriver(
                context.repo,
                driver
            )
            if driver != model.rdf_dbDriver:
                model = model.rdf_clone(
                    model.rdf_initDriver(
                        driver
                    )
                )
        return model
    
    def createContentContainer(self, context, node, locale):
        model = context.model
        root = context.defaults.document_root
               
        # get matching contained nodes
        nodes = self.filterContainedNodes(
            context,
            [],
            model,
            locale
        )
                        
        # extract for opt
        #nxa = node.xml_append
        #nxc = node.xml_create_element
        
        if len(nodes):
            self.createContainerNodes(
                context,
                node.xml_append(
                    node.xml_create_element(
                        u'a:grouping', MYELINS,
                        attributes = {
                            u'role'         : u'container',
                            u'key'          : self.groupingKey,
                            u'count'        : unicode(len(nodes)),
                        }
                    )
                ),
                OrderByKeys(
                    model,
                    nodes
                ),
                root,
                locale
            )
        else:
            self.createContainerNodes(
                context,
                node.xml_append(
                    node.xml_create_element(
                        u'a:grouping', MYELINS,
                        attributes = {
                            u'role'         : u'container',
                            u'key'          : self.groupingKey,
                        }
                    )
                ),
                OrderByKeys(
                    model,
                    nodes
                ),
                root,
                locale
            )
            
        return node
    
    def createContainerNodes(self, context, node, children, root, locale):
        acls = context.acls.getNodeAcls
        
        nxa = node.xml_append
        nxc = node.xml_create_element
        
        cap = self.newProfiler(root, locale).createProfile
        map = context.uriMapper.apply
        for n in children:
            n_join = n.rdf_join
            id = n.rdf_value
            new = nxa(
                nxc(
                    u'a:node', MYELINS,
                    attributes = {
                        u'node-id'      : id,
                        u'uri'          : map(n.rdf_domain),
                        u'tag'          : n_join('mTag'),
                        u'title'        : n_join('dcTitle'),
                        #u'description'  : n_join('dcDescription'),
                        u'language'     : n_join('dcLanguage'),
                        u'created'      : n_join('dctermsCreated'),
                        u'type'         : n_join('rdfType',u'|'),
                    }
                )
            )
            
            new.xml_append(
                new.xml_create_element(
                    u'a:description', MYELINS,
                    content = n_join('dcDescription')
                )
            )
            agentDriver = n.Initialize(
                self.newAgentDriver(
                    context.repo,
                    context.server.graphs[GRAPHS_NS + 'agents']['public']
                )
            )
            for a in n.mLast_Modifier:
                new.modified = n_join('dctermsModified')
                cap(
                    context,
                    new,
                    a,
                    u'a:last-modifier',
                    MYELINS
                )
                        
            for a in n.dcCreator:
                cap(
                    context,
                    new,
                    a,
                    u'a:creator',
                    MYELINS
                )
            
            # FIXME: what about admins?
            # admins have all rights
            attr = {}
            for a in acls(n.rdf_domain):
                attr[a] = u'1'
                
            new.xml_append(
                new.xml_create_element(
                    u'a:node-acls', MYELINS,
                    attributes = attr
                )
            )
            
        return node
    
    def getContainedNodeInitializer(self, context):
        def init(n):
            n.rdf_getDomain()
            return n
        return init
    
    def filterContainedNodes(self, context, nodes, model, locale):                     
        model = self.getModelByMode(context, model)
                
        action = self.containsAction
        acls = context.acls.checkNodeAcls
        n_extend = nodes.extend
        
        # MAX DISPLAY LIMIT
        # if len(nodes) == max_display_limit:
        #   return
        # Should this be a user preference???
        init = self.getContainedNodeInitializer(context)
        
        # filter direct children nodes
        key = self.containsKey        
        n_extend(
            n for n in getattr(model,key) \
            if acls(init(n).rdf_domain,action)
        )
                
        # if model IS A translation of another model,
        # then filter the other models matching translated nodes
        # of the children nodes 
        for t in model.mTranslations:
            for c in getattr(t, key):
                n_extend(
                    n for n in c.mTranslation \
                    if locale in n.dcLanguage and \
                        acls(n.rdf_domain, action)
                )

        return nodes


class Transform(Transform):
    
    newDocument = Document